﻿namespace PJB.FacetedNavigation
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.ServiceModel;
    using Celeriq.Common;

    [Serializable]
    public partial class ListingItem
    {
        public ListingItem()
        {
            _dimensionList = new List<DimensionItem>();
        }

        internal ListingItem(Celeriq.Common.DataItem item, ListingResults results)
            : this()
        {
            this.JobID = (int)item.ItemArray[0];
            this.Specialty = (string)item.ItemArray[1];
            this.PostDate = (DateTime?)item.ItemArray[2];
            this.Job_type = (string)item.ItemArray[3];
            this.Position_type = (string)item.ItemArray[4];
            this.State = (string)item.ItemArray[5];
            this.Description = (string)item.ItemArray[6];
            this.Company = (string)item.ItemArray[7];
            this.Location = (Celeriq.Common.GeoCode)item.ItemArray[8];

            RefinementItem r;
            r = results.AllDimensions.CompanyDimension.GetRefinementByValue(this.Company);
            if (r != null && this.Company != null)
            {
                var d = ((System.ICloneable)results.AllDimensions.CompanyDimension).Clone() as DimensionItem;
                d.RefinementList.RemoveAll(x => x.FieldValue != this.Company);
                d.RefinementList.First().Count = 1;
                _dimensionList.Add(d);
            }

            r = results.AllDimensions.Job_typeDimension.GetRefinementByValue(this.Job_type);
            if (r != null && this.Job_type != null)
            {
                var d = ((System.ICloneable)results.AllDimensions.Job_typeDimension).Clone() as DimensionItem;
                d.RefinementList.RemoveAll(x => x.FieldValue != this.Job_type);
                d.RefinementList.First().Count = 1;
                _dimensionList.Add(d);
            }

            r = results.AllDimensions.Position_typeDimension.GetRefinementByValue(this.Position_type);
            if (r != null && this.Position_type != null)
            {
                var d = ((System.ICloneable)results.AllDimensions.Position_typeDimension).Clone() as DimensionItem;
                d.RefinementList.RemoveAll(x => x.FieldValue != this.Position_type);
                d.RefinementList.First().Count = 1;
                _dimensionList.Add(d);
            }

            r = results.AllDimensions.SpecialtyDimension.GetRefinementByValue(this.Specialty);
            if (r != null && this.Specialty != null)
            {
                var d = ((System.ICloneable)results.AllDimensions.SpecialtyDimension).Clone() as DimensionItem;
                d.RefinementList.RemoveAll(x => x.FieldValue != this.Specialty);
                d.RefinementList.First().Count = 1;
                _dimensionList.Add(d);
            }

            r = results.AllDimensions.StateDimension.GetRefinementByValue(this.State);
            if (r != null && this.State != null)
            {
                var d = ((System.ICloneable)results.AllDimensions.StateDimension).Clone() as DimensionItem;
                d.RefinementList.RemoveAll(x => x.FieldValue != this.State);
                d.RefinementList.First().Count = 1;
                _dimensionList.Add(d);
            }

        }

        public int JobID { get; set; }
        public string Specialty { get; set; }
        public DateTime? PostDate { get; set; }
        public string Job_type { get; set; }
        public string Position_type { get; set; }
        public string State { get; set; }
        public string Description { get; set; }
        public string Company { get; set; }
        public Celeriq.Common.GeoCode Location { get; set; }
        private readonly List<DimensionItem> _dimensionList = null;
        public IEnumerable<DimensionItem> DimensionList
        {
            get { return _dimensionList; }
        }

        private static long FloorToNearest(long d, long n)
        {
            if (n <= 0) throw new Exception("The rounding operation cannot be performed.");
            return d - (d % n);
        }

        public Celeriq.Common.DataItem ToTransfer()
        {
            var retval = new Celeriq.Common.DataItem();
            retval.ItemArray = new object[] {
                this.JobID,
                this.Specialty,
                this.PostDate,
                this.Job_type,
                this.Position_type,
                this.State,
                this.Description,
                this.Company,
                this.Location,
            };
            return retval;
        }
    }

    [Serializable]
    public partial class ListingQuery : Celeriq.Common.BaseListingQuery, System.ICloneable
    {
        partial void LoadFromUrlComplete(string originalUrl);

        public ListingQuery()
            : base()
        {
        }

        internal ListingQuery(Celeriq.Common.DataQuery query)
            : this()
        {
            this.DimensionValueList.AddRange(query.DimensionValueList);
            this.PageOffset = query.PageOffset;
            this.RecordsPerPage = query.RecordsPerPage;
            this.Keyword = query.Keyword;
            this.PageName = query.PageName;
            this.NonParsedFieldList = new NamedItemList();
            if (query.NonParsedFieldList != null)
                this.NonParsedFieldList.AddRange(query.NonParsedFieldList);

            #region Field Filters
            if (query.FieldFilters != null)
            {
                foreach (var ff in query.FieldFilters)
                {
                    switch (ff.Name)
                    {
                        case "JobID":
                            this.FieldFilters.Add(new FieldFilterJobID { JobID = (int?)ff.Value, Comparer = ff.Comparer });
                            break;
                        case "Specialty":
                            this.FieldFilters.Add(new FieldFilterSpecialty { Specialty = (string)ff.Value, Comparer = ff.Comparer });
                            break;
                        case "PostDate":
                            this.FieldFilters.Add(new FieldFilterPostDate { PostDate = (DateTime?)ff.Value, Comparer = ff.Comparer });
                            break;
                        case "Job_type":
                            this.FieldFilters.Add(new FieldFilterJob_type { Job_type = (string)ff.Value, Comparer = ff.Comparer });
                            break;
                        case "Position_type":
                            this.FieldFilters.Add(new FieldFilterPosition_type { Position_type = (string)ff.Value, Comparer = ff.Comparer });
                            break;
                        case "State":
                            this.FieldFilters.Add(new FieldFilterState { State = (string)ff.Value, Comparer = ff.Comparer });
                            break;
                        case "Description":
                            this.FieldFilters.Add(new FieldFilterDescription { Description = (string)ff.Value, Comparer = ff.Comparer });
                            break;
                        case "Company":
                            this.FieldFilters.Add(new FieldFilterCompany { Company = (string)ff.Value, Comparer = ff.Comparer });
                            break;
                        case "Location":
                            this.FieldFilters.Add(new FieldFilterLocation()
                            {
                                Latitude = ((Celeriq.Common.GeoCodeFieldFilter)ff).Latitude,
                                Longitude = ((Celeriq.Common.GeoCodeFieldFilter)ff).Longitude,
                                Radius = ((Celeriq.Common.GeoCodeFieldFilter)ff).Radius,
                                Comparer = ff.Comparer,
                            });
                            break;
                        default:
                            throw new Exception("Unknown filter!");
                    }
                }
            }
            #endregion

            #region Field Sorts
            if (query.FieldSorts != null)
            {
                foreach (var fs in query.FieldSorts)
                {
                    switch (fs.Name)
                    {
                        case "JobID":
                            this.FieldSorts.Add(new FieldSortJobID { Name = fs.Name, SortDirection = fs.SortDirection });
                            break;
                        case "Specialty":
                            this.FieldSorts.Add(new FieldSortSpecialty { Name = fs.Name, SortDirection = fs.SortDirection });
                            break;
                        case "PostDate":
                            this.FieldSorts.Add(new FieldSortPostDate { Name = fs.Name, SortDirection = fs.SortDirection });
                            break;
                        case "Job_type":
                            this.FieldSorts.Add(new FieldSortJob_type { Name = fs.Name, SortDirection = fs.SortDirection });
                            break;
                        case "Position_type":
                            this.FieldSorts.Add(new FieldSortPosition_type { Name = fs.Name, SortDirection = fs.SortDirection });
                            break;
                        case "State":
                            this.FieldSorts.Add(new FieldSortState { Name = fs.Name, SortDirection = fs.SortDirection });
                            break;
                        case "Description":
                            this.FieldSorts.Add(new FieldSortDescription { Name = fs.Name, SortDirection = fs.SortDirection });
                            break;
                        case "Company":
                            this.FieldSorts.Add(new FieldSortCompany { Name = fs.Name, SortDirection = fs.SortDirection });
                            break;
                        default:
                            throw new Exception("Unknown sort!");
                    }
                }
            }
            #endregion

        }

        public ListingQuery(string url)
            : this()
        {
            if (string.IsNullOrEmpty(url)) return;
            if (url.Contains("%")) url = System.Web.HttpUtility.UrlDecode(url);
            var originalUrl = url;

            var pageBreak = url.IndexOf('?');
            if (pageBreak != -1 && pageBreak < url.Length - 1)
            {
                this.PageName = url.Substring(0, pageBreak);
                url = url.Substring(pageBreak + 1, url.Length - pageBreak - 1);
            }
            else
            {
                this.PageName = url;
                return;
            }

            #region Parse Query String
            var tuplets = url.Split('&');
            foreach (var gset in tuplets)
            {
                var values = gset.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
                if (values.Length == 2)
                {
                    switch (values[0])
                    {
                        case "d":
                            {
                                var dValues = values[1].Split(new char[] { '+', ' ' }, StringSplitOptions.RemoveEmptyEntries);
                                foreach (var dvidxV in dValues)
                                {
                                    long dvidx;
                                    if (long.TryParse(dvidxV, out dvidx))
                                        this.DimensionValueList.Add(dvidx);
                                }
                            }
                            break;
                        case "po":
                            {
                                int po;
                                if (int.TryParse(values[1], out po))
                                    this.PageOffset = po;
                            }
                            break;
                        case "rpp":
                            {
                                int rpp;
                                if (int.TryParse(values[1], out rpp))
                                    this.RecordsPerPage = rpp;
                            }
                            break;
                        case "ff":
                            {
                                var filters = values[1].Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
                                foreach (var s in filters)
                                {
                                    var svalues = s.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                                    if (svalues.Length >= 3)
                                    {
                                        Celeriq.Common.ComparisonConstants enumValue;
                                        if (Enum.TryParse<Celeriq.Common.ComparisonConstants>(svalues[1], out enumValue))
                                        {
                                            switch (svalues[0].ToLower())
                                            {
                                                case "company":
                                                    this.FieldFilters.Add(new FieldFilterCompany() { Name = "Company", Comparer = enumValue, Company = svalues[2] });
                                                    if (enumValue == Celeriq.Common.ComparisonConstants.Between)
                                                    {
                                                        if (svalues.Length > 3)
                                                            this.FieldFilters.Last().Value2 = svalues[3];
                                                        else
                                                            throw new Exception("The URL for field filter 'Company' is invalid!");
                                                    }
                                                    break;
                                                case "description":
                                                    this.FieldFilters.Add(new FieldFilterDescription() { Name = "Description", Comparer = enumValue, Description = svalues[2] });
                                                    if (enumValue == Celeriq.Common.ComparisonConstants.Between)
                                                    {
                                                        if (svalues.Length > 3)
                                                            this.FieldFilters.Last().Value2 = svalues[3];
                                                        else
                                                            throw new Exception("The URL for field filter 'Description' is invalid!");
                                                    }
                                                    break;
                                                case "job_type":
                                                    this.FieldFilters.Add(new FieldFilterJob_type() { Name = "Job_type", Comparer = enumValue, Job_type = svalues[2] });
                                                    if (enumValue == Celeriq.Common.ComparisonConstants.Between)
                                                    {
                                                        if (svalues.Length > 3)
                                                            this.FieldFilters.Last().Value2 = svalues[3];
                                                        else
                                                            throw new Exception("The URL for field filter 'Job_type' is invalid!");
                                                    }
                                                    break;
                                                case "jobid":
                                                    int jobidValue;
                                                    if (int.TryParse(svalues[2], out jobidValue))
                                                        this.FieldFilters.Add(new FieldFilterJobID() { Name = "JobID", Comparer = enumValue, JobID = jobidValue });
                                                    if (enumValue == Celeriq.Common.ComparisonConstants.Between)
                                                    {
                                                        if (svalues.Length > 3)
                                                        {
                                                            if (int.TryParse(svalues[3], out jobidValue))
                                                                this.FieldFilters.Last().Value2 = jobidValue;
                                                            else
                                                                throw new Exception("The URL for field filter 'JobID' is invalid!");
                                                        }
                                                        else
                                                            throw new Exception("The URL for field filter 'JobID' is invalid!");
                                                    }
                                                    break;
                                                case "location":
                                                    double locationValue1, locationValue2, radius;
                                                    if (svalues.Length > 4)
                                                    {
                                                        if (double.TryParse(svalues[2], out locationValue1) && double.TryParse(svalues[3], out locationValue2) && double.TryParse(svalues[4], out radius))
                                                            this.FieldFilters.Add(new FieldFilterLocation() { Name = "Location", Comparer = enumValue, Latitude = locationValue1, Longitude = locationValue2, Radius = radius });
                                                        else
                                                            throw new Exception("The URL for field filter 'Location' is invalid!");
                                                    }
                                                    else
                                                        throw new Exception("The URL for field filter 'Location' is invalid!");
                                                    break;
                                                case "position_type":
                                                    this.FieldFilters.Add(new FieldFilterPosition_type() { Name = "Position_type", Comparer = enumValue, Position_type = svalues[2] });
                                                    if (enumValue == Celeriq.Common.ComparisonConstants.Between)
                                                    {
                                                        if (svalues.Length > 3)
                                                            this.FieldFilters.Last().Value2 = svalues[3];
                                                        else
                                                            throw new Exception("The URL for field filter 'Position_type' is invalid!");
                                                    }
                                                    break;
                                                case "postdate":
                                                    DateTime postdateValue;
                                                    if (DateTime.TryParse(svalues[2], out postdateValue))
                                                        this.FieldFilters.Add(new FieldFilterPostDate() { Name = "PostDate", Comparer = enumValue, PostDate = postdateValue });
                                                    if (enumValue == Celeriq.Common.ComparisonConstants.Between)
                                                    {
                                                        if (svalues.Length > 3)
                                                        {
                                                            if (DateTime.TryParse(svalues[3], out postdateValue))
                                                                this.FieldFilters.Last().Value2 = postdateValue;
                                                            else
                                                                throw new Exception("The URL for field filter 'PostDate' is invalid!");
                                                        }
                                                        else
                                                            throw new Exception("The URL for field filter 'PostDate' is invalid!");
                                                    }
                                                    break;
                                                case "specialty":
                                                    this.FieldFilters.Add(new FieldFilterSpecialty() { Name = "Specialty", Comparer = enumValue, Specialty = svalues[2] });
                                                    if (enumValue == Celeriq.Common.ComparisonConstants.Between)
                                                    {
                                                        if (svalues.Length > 3)
                                                            this.FieldFilters.Last().Value2 = svalues[3];
                                                        else
                                                            throw new Exception("The URL for field filter 'Specialty' is invalid!");
                                                    }
                                                    break;
                                                case "state":
                                                    this.FieldFilters.Add(new FieldFilterState() { Name = "State", Comparer = enumValue, State = svalues[2] });
                                                    if (enumValue == Celeriq.Common.ComparisonConstants.Between)
                                                    {
                                                        if (svalues.Length > 3)
                                                            this.FieldFilters.Last().Value2 = svalues[3];
                                                        else
                                                            throw new Exception("The URL for field filter 'State' is invalid!");
                                                    }
                                                    break;
                                            }
                                        }
                                    }
                                }
                            }
                            break;
                        case "fs":
                            {
                                var sorts = values[1].Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
                                foreach (var s in sorts)
                                {
                                    var svalues = s.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                                    if (svalues.Length > 0)
                                    {
                                        switch (svalues[0].ToLower())
                                        {
                                            case "company":
                                                this.FieldSorts.Add(new FieldSortCompany() { Name = "Company", SortDirection = (svalues.Length == 1 || svalues[1] != "0" ? Celeriq.Common.SortDirectionConstants.Asc : Celeriq.Common.SortDirectionConstants.Desc) });
                                                break;
                                            case "description":
                                                this.FieldSorts.Add(new FieldSortDescription() { Name = "Description", SortDirection = (svalues.Length == 1 || svalues[1] != "0" ? Celeriq.Common.SortDirectionConstants.Asc : Celeriq.Common.SortDirectionConstants.Desc) });
                                                break;
                                            case "job_type":
                                                this.FieldSorts.Add(new FieldSortJob_type() { Name = "Job_type", SortDirection = (svalues.Length == 1 || svalues[1] != "0" ? Celeriq.Common.SortDirectionConstants.Asc : Celeriq.Common.SortDirectionConstants.Desc) });
                                                break;
                                            case "jobid":
                                                this.FieldSorts.Add(new FieldSortJobID() { Name = "JobID", SortDirection = (svalues.Length == 1 || svalues[1] != "0" ? Celeriq.Common.SortDirectionConstants.Asc : Celeriq.Common.SortDirectionConstants.Desc) });
                                                break;
                                            case "position_type":
                                                this.FieldSorts.Add(new FieldSortPosition_type() { Name = "Position_type", SortDirection = (svalues.Length == 1 || svalues[1] != "0" ? Celeriq.Common.SortDirectionConstants.Asc : Celeriq.Common.SortDirectionConstants.Desc) });
                                                break;
                                            case "postdate":
                                                this.FieldSorts.Add(new FieldSortPostDate() { Name = "PostDate", SortDirection = (svalues.Length == 1 || svalues[1] != "0" ? Celeriq.Common.SortDirectionConstants.Asc : Celeriq.Common.SortDirectionConstants.Desc) });
                                                break;
                                            case "specialty":
                                                this.FieldSorts.Add(new FieldSortSpecialty() { Name = "Specialty", SortDirection = (svalues.Length == 1 || svalues[1] != "0" ? Celeriq.Common.SortDirectionConstants.Asc : Celeriq.Common.SortDirectionConstants.Desc) });
                                                break;
                                            case "state":
                                                this.FieldSorts.Add(new FieldSortState() { Name = "State", SortDirection = (svalues.Length == 1 || svalues[1] != "0" ? Celeriq.Common.SortDirectionConstants.Asc : Celeriq.Common.SortDirectionConstants.Desc) });
                                                break;
                                        }
                                    }
                                }
                            }
                            break;
                        case "srch":
                            this.Keyword = values[1];
                            break;
                        default:
                            if (values.Length >= 2)
                            {
                                if (this.NonParsedFieldList.Count(x => x.Key == values[0]) > 0)
                                    this.NonParsedFieldList.First(x => x.Key == values[0]).Value = values[1];
                                else
                                    this.NonParsedFieldList.Add(new NamedItem() { Key = values[0], Value = values[1] });
                            }
                            break;
                    }
                }
            }
            #endregion

            LoadFromUrlComplete(originalUrl);

        }

        public static Celeriq.Common.FieldSort GetSortByName(string name)
        {
            if (name == "JobID") return new FieldSortJobID() { Name = "JobID", SortDirection = Celeriq.Common.SortDirectionConstants.Asc };
            if (name == "Specialty") return new FieldSortSpecialty() { Name = "Specialty", SortDirection = Celeriq.Common.SortDirectionConstants.Asc };
            if (name == "PostDate") return new FieldSortPostDate() { Name = "PostDate", SortDirection = Celeriq.Common.SortDirectionConstants.Asc };
            if (name == "Job_type") return new FieldSortJob_type() { Name = "Job_type", SortDirection = Celeriq.Common.SortDirectionConstants.Asc };
            if (name == "Position_type") return new FieldSortPosition_type() { Name = "Position_type", SortDirection = Celeriq.Common.SortDirectionConstants.Asc };
            if (name == "State") return new FieldSortState() { Name = "State", SortDirection = Celeriq.Common.SortDirectionConstants.Asc };
            if (name == "Description") return new FieldSortDescription() { Name = "Description", SortDirection = Celeriq.Common.SortDirectionConstants.Asc };
            if (name == "Company") return new FieldSortCompany() { Name = "Company", SortDirection = Celeriq.Common.SortDirectionConstants.Asc };
            return null;
        }

        public Celeriq.Common.DataQuery ToTransfer()
        {
            var retval = new Celeriq.Common.DataQuery();
            retval.DimensionValueList = this.DimensionValueList;

            retval.FieldFilters = new List<Celeriq.Common.IFieldFilter>();
            if (this.FieldFilters == null)
                this.FieldFilters = new List<IFieldFilter>();
            foreach (var o in this.FieldFilters)
            {
                if (o is Celeriq.Common.GeoCodeFieldFilter)
                {
                    var newFilter = new Celeriq.Common.GeoCodeFieldFilter()
                    {
                        Latitude = ((Celeriq.Common.GeoCodeFieldFilter)o).Latitude,
                        Longitude = ((Celeriq.Common.GeoCodeFieldFilter)o).Longitude,
                        Radius = ((Celeriq.Common.GeoCodeFieldFilter)o).Radius,
                        Comparer = o.Comparer,
                        Name = o.Name,
                    };
                    ((Celeriq.Common.IFieldFilter)newFilter).Value = ((Celeriq.Common.IFieldFilter)o).Value;
                    ((Celeriq.Common.IFieldFilter)newFilter).Value2 = ((Celeriq.Common.IFieldFilter)o).Value2;
                    retval.FieldFilters.Add(newFilter);
                }
                else
                {
                    var newFilter = new Celeriq.Common.FieldFilter()
                    {
                        Comparer = o.Comparer,
                        Name = o.Name,
                    };
                    ((Celeriq.Common.IFieldFilter)newFilter).Value = ((Celeriq.Common.IFieldFilter)o).Value;
                    ((Celeriq.Common.IFieldFilter)newFilter).Value2 = ((Celeriq.Common.IFieldFilter)o).Value2;
                    retval.FieldFilters.Add(newFilter);
                }
            }

            retval.FieldSorts = new List<Celeriq.Common.IFieldSort>();
            if (this.FieldSorts == null)
                this.FieldSorts = new List<IFieldSort>();
            foreach (var o in this.FieldSorts)
            {
                retval.FieldSorts.Add(new Celeriq.Common.FieldSort()
                {
                    Name = o.Name,
                    SortDirection = o.SortDirection,
                });
            }

            if (this.NonParsedFieldList != null)
            {
                this.NonParsedFieldList.ForEach(x => retval.NonParsedFieldList.Add(x));
            }

            retval.Keyword = this.Keyword;
            retval.PageOffset = this.PageOffset;
            retval.RecordsPerPage = this.RecordsPerPage;
            return retval;
        }

        public override string ToString()
        {
            var retval = string.Empty;

            #region Dimensions
            if (this.DimensionValueList != null && this.DimensionValueList.Count > 0)
            {
                retval += "d=" + string.Join("+", this.DimensionValueList.Select(x => x.ToString()));
            }
            #endregion

            #region Field Filters
            if (this.FieldFilters != null && this.FieldFilters.Count > 0)
            {
                var ffURL = string.Empty;
                foreach (var ff in this.FieldFilters)
                {
                    var fieldName = string.Empty;
                    if (1 == 0) ;
                    else if (ff is FieldFilterCompany) fieldName = "Company";
                    else if (ff is FieldFilterDescription) fieldName = "Description";
                    else if (ff is FieldFilterJob_type) fieldName = "Job_type";
                    else if (ff is FieldFilterJobID) fieldName = "JobID";
                    else if (ff is FieldFilterLocation) fieldName = "Location";
                    else if (ff is FieldFilterPosition_type) fieldName = "Position_type";
                    else if (ff is FieldFilterPostDate) fieldName = "PostDate";
                    else if (ff is FieldFilterSpecialty) fieldName = "Specialty";
                    else if (ff is FieldFilterState) fieldName = "State";
                    else throw new Exception("The filter type is not valid!");

                    var f1 = (Celeriq.Common.IFieldFilter)ff;
                    if (ff is Celeriq.Common.GeoCodeFieldFilter)
                    {
                        var gff = ff as Celeriq.Common.GeoCodeFieldFilter;
                        ffURL += fieldName + "," + ff.Comparer.ToString() + "," + gff.Latitude.ToString() + "," + gff.Longitude.ToString() + "," + gff.Radius.ToString() + "|";
                    }
                    else
                    {
                        if (ff.Comparer == Celeriq.Common.ComparisonConstants.Between)
                        {
                            if ((f1.Value != null) && (f1.Value2 != null))
                            {
                                ffURL += fieldName + "," + ff.Comparer.ToString() + "," + f1.Value.ToString() + "," + f1.Value2.ToString() + "|";
                            }
                        }
                        else
                        {
                            if (f1.Value != null)
                            {
                                ffURL += fieldName + "," + ff.Comparer.ToString() + "," + f1.Value.ToString() + "|";
                            }
                        }
                    }
                }

                ffURL = ffURL.Trim('|');
                if (!string.IsNullOrEmpty(ffURL))
                    retval += "&ff=" + ffURL;
            }
            #endregion

            #region Field Sorts
            if (this.FieldSorts != null && this.FieldSorts.Count > 0)
            {
                var fsURL = string.Empty;
                foreach (var fs in this.FieldSorts)
                {
                    if (1 == 0) ;
                    else if (fs is FieldSortCompany) fsURL += "Company";
                    else if (fs is FieldSortDescription) fsURL += "Description";
                    else if (fs is FieldSortJob_type) fsURL += "Job_type";
                    else if (fs is FieldSortJobID) fsURL += "JobID";
                    else if (fs is FieldSortPosition_type) fsURL += "Position_type";
                    else if (fs is FieldSortPostDate) fsURL += "PostDate";
                    else if (fs is FieldSortSpecialty) fsURL += "Specialty";
                    else if (fs is FieldSortState) fsURL += "State";
                    else throw new Exception("The sort type is not valid!");
                    fsURL += (fs.SortDirection == Celeriq.Common.SortDirectionConstants.Asc ? string.Empty : ",0");
                }

                fsURL = fsURL.Trim('|');
                if (!string.IsNullOrEmpty(fsURL))
                    retval += "&fs=" + fsURL;
            }
            #endregion

            #region Keyword
            if (!string.IsNullOrEmpty(this.Keyword))
            {
                retval += "&srch=" + this.Keyword;
            }
            #endregion

            if (this.PageOffset != 1)
                retval += "&po=" + this.PageOffset;
            if (this.RecordsPerPage != 10)
                retval += "&rpp=" + this.RecordsPerPage;

            #region NonParsed Field
            if (this.NonParsedFieldList != null)
            {
                foreach (var item in this.NonParsedFieldList.Where(x => !string.IsNullOrEmpty(x.Value)))
                {
                    retval += "&" + item.Key + "=" + item.Value;
                }
            }
            #endregion

            retval = retval.Trim('&');

            if (string.IsNullOrEmpty(this.PageName))
                return retval;
            else if (!string.IsNullOrEmpty(retval))
                return this.PageName + "?" + retval;
            else
                return this.PageName;
        }

        partial void Cloning(ListingQuery query);

        object ICloneable.Clone()
        {
            return this.Clone();
        }

        public ListingQuery Clone()
        {
            var retval = new ListingQuery();
            retval.DimensionValueList.AddRange(this.DimensionValueList);
            retval.FieldFilters.AddRange(this.FieldFilters);
            retval.FieldSorts.AddRange(this.FieldSorts);
            retval.Keyword = this.Keyword;
            retval.NonParsedFieldList.AddRange(this.NonParsedFieldList);
            retval.PageOffset = this.PageOffset;
            retval.PageName = this.PageName;
            retval.RecordsPerPage = this.RecordsPerPage;
            this.Cloning(retval);
            return retval;
        }

    }

    #region Filtering

    [Serializable]
    public sealed class FieldFilterJobID : Celeriq.Common.FieldFilter, Celeriq.Common.IFieldFilter
    {
        public FieldFilterJobID() : base("JobID") { }
        public int? JobID { get; set; }
        object Celeriq.Common.IFieldFilter.Value
        {
            get { return this.JobID; }
            set { this.JobID = (int?)value; }
        }
    }

    [Serializable]
    public sealed class FieldFilterSpecialty : Celeriq.Common.FieldFilter, Celeriq.Common.IFieldFilter
    {
        public FieldFilterSpecialty() : base("Specialty") { }
        public string Specialty { get; set; }
        object Celeriq.Common.IFieldFilter.Value
        {
            get { return this.Specialty; }
            set { this.Specialty = (string)value; }
        }
    }

    [Serializable]
    public sealed class FieldFilterPostDate : Celeriq.Common.FieldFilter, Celeriq.Common.IFieldFilter
    {
        public FieldFilterPostDate() : base("PostDate") { }
        public DateTime? PostDate { get; set; }
        object Celeriq.Common.IFieldFilter.Value
        {
            get { return this.PostDate; }
            set { this.PostDate = (DateTime?)value; }
        }
    }

    [Serializable]
    public sealed class FieldFilterJob_type : Celeriq.Common.FieldFilter, Celeriq.Common.IFieldFilter
    {
        public FieldFilterJob_type() : base("Job_type") { }
        public string Job_type { get; set; }
        object Celeriq.Common.IFieldFilter.Value
        {
            get { return this.Job_type; }
            set { this.Job_type = (string)value; }
        }
    }

    [Serializable]
    public sealed class FieldFilterPosition_type : Celeriq.Common.FieldFilter, Celeriq.Common.IFieldFilter
    {
        public FieldFilterPosition_type() : base("Position_type") { }
        public string Position_type { get; set; }
        object Celeriq.Common.IFieldFilter.Value
        {
            get { return this.Position_type; }
            set { this.Position_type = (string)value; }
        }
    }

    [Serializable]
    public sealed class FieldFilterState : Celeriq.Common.FieldFilter, Celeriq.Common.IFieldFilter
    {
        public FieldFilterState() : base("State") { }
        public string State { get; set; }
        object Celeriq.Common.IFieldFilter.Value
        {
            get { return this.State; }
            set { this.State = (string)value; }
        }
    }

    [Serializable]
    public sealed class FieldFilterDescription : Celeriq.Common.FieldFilter, Celeriq.Common.IFieldFilter
    {
        public FieldFilterDescription() : base("Description") { }
        public string Description { get; set; }
        object Celeriq.Common.IFieldFilter.Value
        {
            get { return this.Description; }
            set { this.Description = (string)value; }
        }
    }

    [Serializable]
    public sealed class FieldFilterCompany : Celeriq.Common.FieldFilter, Celeriq.Common.IFieldFilter
    {
        public FieldFilterCompany() : base("Company") { }
        public string Company { get; set; }
        object Celeriq.Common.IFieldFilter.Value
        {
            get { return this.Company; }
            set { this.Company = (string)value; }
        }
    }

    [Serializable]
    public sealed class FieldFilterLocation : Celeriq.Common.GeoCodeFieldFilter, Celeriq.Common.IFieldFilter
    {
        public FieldFilterLocation() : base("Location") { }
    }

    #endregion

    #region Sorting

    [Serializable]
    public sealed class FieldSortJobID : Celeriq.Common.FieldSort, Celeriq.Common.IFieldSort
    {
        public FieldSortJobID() : base("JobID") { }
    }

    [Serializable]
    public sealed class FieldSortSpecialty : Celeriq.Common.FieldSort, Celeriq.Common.IFieldSort
    {
        public FieldSortSpecialty() : base("Specialty") { }
    }

    [Serializable]
    public sealed class FieldSortPostDate : Celeriq.Common.FieldSort, Celeriq.Common.IFieldSort
    {
        public FieldSortPostDate() : base("PostDate") { }
    }

    [Serializable]
    public sealed class FieldSortJob_type : Celeriq.Common.FieldSort, Celeriq.Common.IFieldSort
    {
        public FieldSortJob_type() : base("Job_type") { }
    }

    [Serializable]
    public sealed class FieldSortPosition_type : Celeriq.Common.FieldSort, Celeriq.Common.IFieldSort
    {
        public FieldSortPosition_type() : base("Position_type") { }
    }

    [Serializable]
    public sealed class FieldSortState : Celeriq.Common.FieldSort, Celeriq.Common.IFieldSort
    {
        public FieldSortState() : base("State") { }
    }

    [Serializable]
    public sealed class FieldSortDescription : Celeriq.Common.FieldSort, Celeriq.Common.IFieldSort
    {
        public FieldSortDescription() : base("Description") { }
    }

    [Serializable]
    public sealed class FieldSortCompany : Celeriq.Common.FieldSort, Celeriq.Common.IFieldSort
    {
        public FieldSortCompany() : base("Company") { }
    }

    #endregion

    [Serializable]
    public partial class ListingResults
    {
        private const int VERSION_HASH = -1972878410;

        public ListingResults()
        {
            this.Query = new ListingQuery();
            this.DimensionList = new List<Celeriq.Common.DimensionItem>();
            this.AllDimensions = new DimensionStore(this);
            this.RecordList = new List<ListingItem>();
        }

        internal ListingResults(Celeriq.Common.DataQueryResults results)
            : this()
        {
            if (results.VersionHash != VERSION_HASH)
            {
                throw new Exception("The generated API is out of date. The repository model has been changed. Please re-generate this code file.");
            }

            this.Query = new ListingQuery(results.Query);
            this.DimensionList = new List<Celeriq.Common.DimensionItem>(results.DimensionList);
            this.AllDimensions = new DimensionStore(this);
            this.TotalRecordCount = results.TotalRecordCount;
            if (results.Query.RecordsPerPage > 0)
                this.TotalPageCount = (results.TotalRecordCount / results.Query.RecordsPerPage) + (results.TotalRecordCount % results.Query.RecordsPerPage == 0 ? 0 : 1);
            this.ComputeTime = results.ComputeTime;

            if (results.RecordList != null)
            {
                foreach (var item in results.RecordList)
                {
                    this.RecordList.Add(new ListingItem(item, this));
                }
            }

        }

        public List<Celeriq.Common.DimensionItem> DimensionList { get; private set; }
        public ListingQuery Query { get; private set; }
        public List<ListingItem> RecordList { get; private set; }
        public int TotalRecordCount { get; private set; }
        public int TotalPageCount { get; private set; }
        public DimensionStore AllDimensions { get; private set; }
        public long ComputeTime { get; private set; }

    }

    [Serializable]
    public partial class DimensionStore
    {
        private ListingResults _results = null;
        public DimensionStore(ListingResults results)
        {
            _results = results;
        }

        public Celeriq.Common.DimensionItem CompanyDimension
        {
            get
            {
                var index = _results.DimensionList.IndexOf(_results.DimensionList.FirstOrDefault(x => x.Name == "Company"));
                if (index == -1) return new DimensionItem() { Name = "Company", DIdx = 0, NumericBreak = null };
                else return _results.DimensionList[index];
            }
        }
        public Celeriq.Common.DimensionItem Job_typeDimension
        {
            get
            {
                var index = _results.DimensionList.IndexOf(_results.DimensionList.FirstOrDefault(x => x.Name == "Job type"));
                if (index == -1) return new DimensionItem() { Name = "Job type", DIdx = 0, NumericBreak = null };
                else return _results.DimensionList[index];
            }
        }
        public Celeriq.Common.DimensionItem Position_typeDimension
        {
            get
            {
                var index = _results.DimensionList.IndexOf(_results.DimensionList.FirstOrDefault(x => x.Name == "Position type"));
                if (index == -1) return new DimensionItem() { Name = "Position type", DIdx = 0, NumericBreak = null };
                else return _results.DimensionList[index];
            }
        }
        public Celeriq.Common.DimensionItem SpecialtyDimension
        {
            get
            {
                var index = _results.DimensionList.IndexOf(_results.DimensionList.FirstOrDefault(x => x.Name == "Specialty"));
                if (index == -1) return new DimensionItem() { Name = "Specialty", DIdx = 0, NumericBreak = null };
                else return _results.DimensionList[index];
            }
        }
        public Celeriq.Common.DimensionItem StateDimension
        {
            get
            {
                var index = _results.DimensionList.IndexOf(_results.DimensionList.FirstOrDefault(x => x.Name == "State"));
                if (index == -1) return new DimensionItem() { Name = "State", DIdx = 0, NumericBreak = null };
                else return _results.DimensionList[index];
            }
        }
    }

    [Serializable]
    public partial class RepositoryConnection
    {
        static RepositoryConnection()
        {
            //This is the default WCF key found in the configuration file.
            //You may set this in the calling code to change this value
            WCFKey = "9f690d08-367f-4d1b-9c4a-1876c9637a12";
            ServerName = "localhost";
        }

        public static string WCFKey { get; set; }
        public static string ServerName { get; set; }

        public static System.ServiceModel.ChannelFactory<Celeriq.Common.IDataModel> GetFactory()
        {
            return GetFactory(RepositoryConnection.ServerName, RepositoryConnection.WCFKey);
        }

        public static System.ServiceModel.ChannelFactory<Celeriq.Common.IDataModel> GetFactory(string serverName, string key)
        {
            var myBinding = new NetTcpBinding();
            myBinding.Security.Mode = SecurityMode.None;
            myBinding.MaxBufferPoolSize = 2147483647;
            myBinding.MaxBufferSize = 2147483647;
            myBinding.MaxConnections = 10;
            myBinding.MaxReceivedMessageSize = 2147483647;
            myBinding.ReaderQuotas.MaxDepth = 2147483647;
            myBinding.ReaderQuotas.MaxStringContentLength = 2147483647;
            myBinding.ReaderQuotas.MaxArrayLength = 2147483647;
            myBinding.ReaderQuotas.MaxBytesPerRead = 2147483647;
            myBinding.ReaderQuotas.MaxNameTableCharCount = 2147483647;
            var endpoint = new EndpointAddress("net.tcp://" + serverName + ":1973/" + key);
            return new System.ServiceModel.ChannelFactory<Celeriq.Common.IDataModel>(myBinding, endpoint);
        }

        public static void Clear(Celeriq.Common.IDataModel service)
        {
            var errorList = service.Clear();
            if (errorList != null && errorList.Length > 0)
            {
                throw new Exception(errorList.First());
            }
        }

        public static void UpdateData(ListingItem item, Celeriq.Common.IDataModel service)
        {
            UpdateData(new List<ListingItem>() { item }, service);
        }

        public static void UpdateData(IEnumerable<ListingItem> list, Celeriq.Common.IDataModel service)
        {
            var l = new List<Celeriq.Common.DataItem>();
            list.ToList().ForEach(x => l.Add(x.ToTransfer()));
            var errorList = service.UpdateData(l);
            if (errorList != null && errorList.Length > 0)
            {
                throw new Exception(errorList.First());
            }
        }

        public static void DeleteData(ListingItem item, Celeriq.Common.IDataModel service)
        {
            DeleteData(new List<ListingItem>() { item }, service);
        }

        public static void DeleteData(IEnumerable<ListingItem> list, Celeriq.Common.IDataModel service)
        {
            var l = new List<Celeriq.Common.DataItem>();
            list.ToList().ForEach(x => l.Add(x.ToTransfer()));
            var errorList = service.DeleteData(l);
            if (errorList != null && errorList.Length > 0)
            {
                throw new Exception(errorList.First());
            }
        }

        public static ListingResults QueryData(ListingQuery query, Celeriq.Common.IDataModel service)
        {
            var t = service.Query(query.ToTransfer());
            if (t.ErrorList != null && t.ErrorList.Length > 0)
            {
                throw new Exception(t.ErrorList.First());
            }
            return new ListingResults(t);
        }

    }

}
